﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Vaffanculo.Presentation.Component.WizardControl
{
    /// <summary>
    /// Interaction logic for WizardForm.xaml
    /// </summary>
    public partial class WizardForm  : Window
    {
        #region class variables
        private readonly IPageComponent _introductionComponent;
        private readonly List<IPageComponent> _configurationComponents;
        private readonly IPageComponent _confirmationComponent;
        private readonly IPageProcessComponent _progressComponent;
        private readonly IPageComponent _resultsComponent;

        private IPageComponent _currentComponent;

        private const bool ShowProcessWarning = true;
        private bool _proceedureComplete;
        private bool _processing;

        private bool _closeConfirmed;

        private readonly CancelDialog _cancelDialog;
        private delegate void RefreshDelegate();
        #endregion

        #region initialization
        public WizardForm(String title, IPageComponent introductionComponent, List<IPageComponent> configurationComponents,
            IPageComponent confirmationComponent, IPageProcessComponent progressComponent, IPageComponent resultsComponent)
        {
            InitializeComponent();
            Title = title;

            _cancelDialog = new CancelDialog(title);
            

            #region store proceedure components
            if (introductionComponent == null || confirmationComponent == null ||
                progressComponent == null || resultsComponent == null ||
                configurationComponents == null || configurationComponents.Count == 0)
            {
                throw new Exception("NULL IProceedureComponent");
            }

            _introductionComponent = introductionComponent;
            _confirmationComponent = confirmationComponent;
            _progressComponent = progressComponent;
            _resultsComponent = resultsComponent;

            _configurationComponents = new List<IPageComponent>();
            foreach (IPageComponent t in configurationComponents)
            {
                _configurationComponents.Add(t);
            }

            #endregion

            #region populate key
            introductionLabel.Content = introductionComponent.KeyText;
            confirmationLabel.Content = confirmationComponent.KeyText;
            progressLabel.Content = progressComponent.KeyText;
            resultsLabel.Content = resultsComponent.KeyText;

            var sP = new StackPanel {Orientation = Orientation.Vertical};
            configurationExpander.Content = sP;

            foreach (IPageComponent t in configurationComponents)
            {
                var configurationLabel = new Label
                                             {
                                                 Content = t.KeyText,
                                                 Margin = new Thickness(30, 0, 0, 0),
                                                 Height = 25,
                                                 Tag = t
                                             };
                configurationLabel.MouseUp += ConfigurationLabelMouseUp;
                sP.Children.Add(configurationLabel);
            }
            #endregion

            #region load introduction
            contentGrid.Children.Add((System.Windows.Controls.UserControl)introductionComponent);
            _currentComponent = introductionComponent;
            #endregion

            #region hook finish process
            progressComponent.ProceedureCompleteDelegates.Add(FinishProcess);
            #endregion

            UpdateKeyLinks();
        }

        public WizardForm(String title, IPageComponent introductionComponent, List<IPageComponent> configurationComponents)
        {
            InitializeComponent();
            Title = title;

            _cancelDialog = new CancelDialog(title);


            #region store proceedure components
            if (introductionComponent == null || configurationComponents.Count == 0)
            {
                throw new Exception("NULL IProceedureComponent");
            }

            _introductionComponent = introductionComponent;
            _confirmationComponent = null;
            _progressComponent = null;
            _resultsComponent = null;

            _configurationComponents = new List<IPageComponent>();
            foreach (IPageComponent t in configurationComponents)
            {
                _configurationComponents.Add(t);
            }

            #endregion

            #region populate key
            introductionLabel.Content = introductionComponent.KeyText;
           /* confirmationLabel.Content = confirmationComponent.KeyText;
            progressLabel.Content = progressComponent.KeyText;
            resultsLabel.Content = resultsComponent.KeyText;*/

            var sP = new StackPanel { Orientation = Orientation.Vertical };
            configurationExpander.Content = sP;

            foreach (IPageComponent t in configurationComponents)
            {
                var configurationLabel = new Label
                {
                    Content = t.KeyText,
                    Margin = new Thickness(30, 0, 0, 0),
                    Height = 25,
                    Tag = t
                };
                configurationLabel.MouseUp += ConfigurationLabelMouseUp;
                sP.Children.Add(configurationLabel);
            }
            #endregion

            #region load introduction
            contentGrid.Children.Add((System.Windows.Controls.UserControl)introductionComponent);
            _currentComponent = introductionComponent;
            #endregion

            #region hook finish process
            //progressComponent.ProceedureCompleteDelegates.Add(FinishProcess);
            #endregion

            UpdateKeyLinks();
        }

        
        #endregion

        #region key handlers
        private void IntroductionLabelMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_currentComponent != _introductionComponent && _currentComponent != _progressComponent &&
                _currentComponent != _resultsComponent)
            {
                #region update key expanders
                if (_currentComponent == _confirmationComponent)
                {
                    confirmationExpander.IsExpanded = false;
                }
                else 
                {
                    configurationExpander.IsExpanded = false;
                }

                introductionExpander.IsExpanded = true;
                #endregion

                _currentComponent = _introductionComponent;
                contentGrid.Children.RemoveRange(0, contentGrid.Children.Count);
                contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

                UpdateButtons();
            }   
        }

        private void ConfigurationLabelMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_currentComponent != ((Label)sender).Tag && _currentComponent != _progressComponent &&
                _currentComponent != _resultsComponent)
            {
                #region update key expanders
                if (_currentComponent == _introductionComponent)
                {
                    introductionExpander.IsExpanded = false;
                    configurationExpander.IsExpanded = true;
                }
                else if (_currentComponent == _confirmationComponent)
                {
                    confirmationExpander.IsExpanded = false;
                    configurationExpander.IsExpanded = true;
                }
                #endregion

                _currentComponent = (IPageComponent)((Label)sender).Tag;
                contentGrid.Children.RemoveRange(0, contentGrid.Children.Count);
                contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

                UpdateButtons();
            }
        }

        private void ConfirmationLabelMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_currentComponent != confirmationExpander && _currentComponent != _progressComponent &&
                _currentComponent != _resultsComponent)
            {
                #region update key expanders
                if (_currentComponent == _introductionComponent)
                {
                    introductionExpander.IsExpanded = false;
                }
                else
                {
                    configurationExpander.IsExpanded = false;
                }

                confirmationExpander.IsExpanded = true;
                #endregion

                _currentComponent = _confirmationComponent;
                contentGrid.Children.RemoveRange(0, contentGrid.Children.Count);
                contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

                UpdateButtons();
            } 
        }

        private void ProgressLabelMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_currentComponent == _resultsComponent)
            {
                #region update key expanders
                resultsExpander.IsExpanded = false;
                progressExpander.IsExpanded = true;
                #endregion

                _currentComponent = _progressComponent;
                contentGrid.Children.RemoveRange(0, contentGrid.Children.Count);
                contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

                UpdateButtons();
            } 
        }

        private void ResultsLabelMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_proceedureComplete && _currentComponent == _progressComponent)
            {
                #region update key expanders
                progressExpander.IsExpanded = false;
                resultsExpander.IsExpanded = true;
                #endregion

                _currentComponent = _resultsComponent;
                contentGrid.Children.RemoveRange(0, contentGrid.Children.Count);
                contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

                UpdateButtons();
            }
        }
        #endregion

        #region back / next / finish handlers
        private void BackButtonClick(object sender, RoutedEventArgs e)
        {
            #region update key expanders
            if (_currentComponent == _configurationComponents[0])
            {
                configurationExpander.IsExpanded = false;
                introductionExpander.IsExpanded = true;
            }
            else if (_currentComponent == _confirmationComponent)
            {
                confirmationExpander.IsExpanded = false;
                configurationExpander.IsExpanded = true;
            }
            else if (_currentComponent == _progressComponent)
            {
                progressExpander.IsExpanded = false;
                confirmationExpander.IsExpanded = true;
            }
            else if (_currentComponent == _resultsComponent)
            {
                resultsExpander.IsExpanded = false;
                progressExpander.IsExpanded = true;
            }
            #endregion

            _currentComponent = GetBack(_currentComponent);
            contentGrid.Children.RemoveAt(0);
            contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

            UpdateButtons();
        }

        private void NextButtonClick(object sender, RoutedEventArgs e)
        {
            #region update key expanders
            if (_currentComponent == _introductionComponent)
            {
                introductionExpander.IsExpanded = false;
                configurationExpander.IsExpanded = true;
            }
            else if (_currentComponent == _configurationComponents[_configurationComponents.Count - 1])
            {
                configurationExpander.IsExpanded = false;
                confirmationExpander.IsExpanded = true;
            }
            else if (_currentComponent == _confirmationComponent)
            {
                confirmationExpander.IsExpanded = false;
                progressExpander.IsExpanded = true;
            }
            else if (_currentComponent == _progressComponent)
            {
                progressExpander.IsExpanded = false;
                resultsExpander.IsExpanded = true;
            }
            #endregion

            _currentComponent = GetNext(_currentComponent);
            contentGrid.Children.RemoveRange(0, contentGrid.Children.Count);
            contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

            UpdateButtons();
        }

        private void FinishButtonClick(object sender, RoutedEventArgs e)
        {
            if (_currentComponent == _confirmationComponent)
            {
                #region confirm action
                if (ShowProcessWarning)
                {
                    if (MessageBox.Show(this, "Final", Title, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Cancel) == MessageBoxResult.Cancel)
                    {
                        return;
                    }
                }
                #endregion

                #region update key expanders
                if (_currentComponent == _introductionComponent)
                {
                    introductionExpander.IsExpanded = false;
                    configurationExpander.IsExpanded = true;
                }
                else if (_currentComponent == _configurationComponents[_configurationComponents.Count - 1])
                {
                    configurationExpander.IsExpanded = false;
                    confirmationExpander.IsExpanded = true;
                }
                else if (_currentComponent == _confirmationComponent)
                {
                    confirmationExpander.IsExpanded = false;
                    progressExpander.IsExpanded = true;
                }
                else if (_currentComponent == _progressComponent)
                {
                    progressExpander.IsExpanded = false;
                    resultsExpander.IsExpanded = true;
                }
                #endregion

                _currentComponent = GetNext(_currentComponent);
                contentGrid.Children.RemoveAt(0);
                contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);

                UpdateButtons();

                _processing = true;

                _progressComponent.StartProceedure();
            }
            else if (_currentComponent == _progressComponent)
            {
                _currentComponent = GetNext(_currentComponent);
                contentGrid.Children.RemoveAt(0);
                contentGrid.Children.Add((System.Windows.Controls.UserControl)_currentComponent);
                UpdateButtons();
            }
            else if (_currentComponent == _resultsComponent)
            {
                _proceedureComplete = true;
                Close();
            }
        }

        private void UpdateButtons()
        {
            if (_currentComponent == _confirmationComponent)
            {
                backButton.IsEnabled = true;
                nextButton.IsEnabled = false;
                finishButton.IsEnabled = true;
            }
            else if (_currentComponent == _introductionComponent)
            {
                backButton.IsEnabled = false;
                nextButton.IsEnabled = true;
                finishButton.IsEnabled = false;
            }
            else if (_currentComponent == _progressComponent)
            {
                backButton.IsEnabled = false;
                nextButton.IsEnabled = false;
                finishButton.IsEnabled = _proceedureComplete; 
            }
            else if (_currentComponent == _resultsComponent)
            {
                backButton.IsEnabled = true;
                nextButton.IsEnabled = false;
                finishButton.IsEnabled = true;
                finishButton.Content = "Fin";
            }
            else
            {
                backButton.IsEnabled = true;
                nextButton.IsEnabled = true;
                finishButton.IsEnabled = false;
            }

            UpdateKeyLinks();
        }

        private void UpdateKeyLinks()
        {
            if (_currentComponent == _introductionComponent || _currentComponent == _confirmationComponent)
            {
                introductionLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                UIElementCollection col = ((StackPanel)(configurationExpander.Content)).Children;
                for (int i = 0; i < col.Count; i++)
                {
                    ((Label)col[i]).Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                }
                confirmationLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                progressLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                resultsLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
            }
            else if (_currentComponent == _progressComponent)
            {
                if (_proceedureComplete)
                {
                    introductionLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                    UIElementCollection col = ((StackPanel)(configurationExpander.Content)).Children;
                    for (int i = 0; i < col.Count; i++)
                    {
                        ((Label)col[i]).Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                    }
                    confirmationLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                    progressLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                    resultsLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                }
                else
                {
                    introductionLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                    UIElementCollection col = ((StackPanel)(configurationExpander.Content)).Children;
                    for (int i = 0; i < col.Count; i++)
                    {
                        ((Label)col[i]).Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                    }
                    confirmationLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                    progressLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                    resultsLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                }
            }
            else if (_currentComponent == _resultsComponent)
            {
                introductionLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                UIElementCollection col = ((StackPanel)(configurationExpander.Content)).Children;
                for (int i = 0; i < col.Count; i++)
                {
                    ((Label)col[i]).Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                }
                confirmationLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                progressLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                resultsLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
            }
            else
            {
                introductionLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                UIElementCollection col = ((StackPanel)(configurationExpander.Content)).Children;
                for (int i = 0; i < col.Count; i++)
                {
                    ((Label)col[i]).Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                }
                confirmationLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Blue"));
                progressLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
                resultsLabel.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Black"));
            }
        }

        private IPageComponent GetNext(IPageComponent current)
        {
            if (_currentComponent == _introductionComponent)
            {
                return _configurationComponents[0];
            }
            if (_currentComponent == _confirmationComponent)
            {
                return _progressComponent;
            }
            if (_currentComponent == _progressComponent)
            {
                return _resultsComponent;
            }
            if (_currentComponent == _resultsComponent)
            {
                return null;
            }
            for (var i = 0; i < _configurationComponents.Count - 1; i++)
            {
                if (_currentComponent == _configurationComponents[i])
                {
                    return _configurationComponents[i + 1];
                }
            }

            return _confirmationComponent;
        }

        private IPageComponent GetBack(IPageComponent current)
        {
            if (_currentComponent == _introductionComponent)
            {
                return null;
            }
            if (_currentComponent == _confirmationComponent)
            {
                return _configurationComponents[_configurationComponents.Count - 1];
            }
            if (_currentComponent == _progressComponent)
            {
                return null;
            }
            if (_currentComponent == _resultsComponent)
            {
                return _progressComponent;
            }
            for (int i = 1; i < _configurationComponents.Count; i++)
            {
                if (_currentComponent == _configurationComponents[i])
                {
                    return _configurationComponents[i - 1];
                }
            }

            return _introductionComponent;
        }
        #endregion

        #region cancel / close handlers
        private void CancelButtonClick(object sender, RoutedEventArgs e)
        {
            if (_processing)
            {
                if (MessageBox.Show(this, "INICIAR CANCELAR", Title, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
                {
                    var t = new Thread(WaitForCancel)
                                   {
                                       Name = "Esperando",
                                       Priority = ThreadPriority.BelowNormal
                                   };
                    t.Start();

                    _cancelDialog.ShowDialog();
                }
            }
            else if (_proceedureComplete)
            {
                _closeConfirmed = true;
                Close();
            }
            else
            {
                if (MessageBox.Show(this, "Seguro desea cancelar", Title, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
                {
                    _closeConfirmed = true;
                    Close();
                }
            }
        }

        private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (!_closeConfirmed)
            {
                if (_processing)
                {
                    if (MessageBox.Show(this, "procesando la cancelacion", Title, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No)
                    {
                        e.Cancel = true;
                    }
                    else
                    {
                        e.Cancel = true;

                        var t = new Thread(WaitForCancel)
                                       {
                                           Name = "Esperando 2",
                                           Priority = ThreadPriority.BelowNormal
                                       };
                        t.Start();

                        _cancelDialog.ShowDialog();
                    }
                }
                else if (_proceedureComplete)
                {
                    e.Cancel = false;
                }
                else
                {
                    e.Cancel = MessageBox.Show(this, "Cancelar Wizard??", Title, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No;
                }
            }
            else
            {
                e.Cancel = false;
            }
        }

        private void WaitForCancel()
        {
            bool result = _progressComponent.CancelProceedure();
            Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new RefreshDelegate(_cancelDialog.Hide));

            if (result)
            {
                _closeConfirmed = true;
                Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new RefreshDelegate(Close));
            }
            else
            {
                Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new RefreshDelegate(WaitForCancelFail));
            }
        }

        private void WaitForCancelFail()
        {
            MessageBox.Show(this, "Error al cancelar", Title, MessageBoxButton.OK, MessageBoxImage.Exclamation, MessageBoxResult.OK);
        }
        #endregion

        #region processing handlers
        private void FinishProcess()
        {
            finishButton.Content = "Finish";
            finishButton.IsEnabled = true;
            _proceedureComplete = true;
            _processing = false;

            Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new RefreshDelegate(UpdateKeyLinks));
        }
        #endregion

        #region accessors
        public IPageComponent IntroductionComponent
        {
            get
            {
                return _introductionComponent;
            }
        }

        public List<IPageComponent> ConfigurationComponents
        {
            get
            {
                var cc = new List<IPageComponent>();
                for (int i = 0; i < _configurationComponents.Count; i++)
                {
                    cc.Add(_configurationComponents[i]);
                }
                return cc;
            }
        }

        public IPageComponent ConfirmationComponent
        {
            get
            {
                return _confirmationComponent;
            }
        }

        public IPageProcessComponent ProgressComponent
        {
            get
            {
                return _progressComponent;
            }
        }

        public IPageComponent ResultsComponent
        {
            get
            {
                return _resultsComponent;
            }
        }

        public String HeaderTitle
        {
            get
            {
                return headingLabel.Content.ToString();
            }
            set
            {
                headingLabel.Content = value;
            }
        }

        public String HeaderDescription
        {
            get
            {
                return summaryLabel.Content.ToString();
            }
            set
            {
                summaryLabel.Content = value;
            }
        }
        #endregion


        private void Window_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
                this.DragMove();
        }


        

    }
}
